import com.asnike.P.bejeweled.Jewel;

private function JEWEL_CLICK( $e:MouseEvent ):void{
	setSelectJewel( $e.target as Jewel );
}
private function setSelectJewel( $target:Jewel ):void{
	if( isSelectedNone() ){
		addJewelFromSelectedJewels( $target );
	}else if( isJewelAlreadySelected( $target ) ){
		removeJewelFromSelectedJewels( $target );
	}else if( isEmptySelectedJewel() && isNearJewel( $target ) ){
		addJewelFromSelectedJewels( $target );
		shiftSelectedJewels( checkSameJewelsOneLine );
	}
}
private function isSelectedNone():Boolean{
	return getSelectedJewels().length === 0;
}
private function isJewelAlreadySelected( $target:Jewel ):Boolean{
	return getSelectedJewels().indexOf( $target ) > -1
}
private function removeJewelFromSelectedJewels( $target:Jewel ):void{
	getSelectedJewels().splice( getSelectedJewels().indexOf( $target ), 1 );
	_view.unselectJewel( $target );
}
private function isEmptySelectedJewel():Boolean{
	return getSelectedJewels().length < 2;
}
private function isNearJewel( $target:Jewel ):Boolean{
	if( isEqualJewelIndexX( $target ) && isInvalidInRangeJewelIndexY( $target ) ){
		return true;
	}else if( isEqualJewelIndexY( $target ) && isInvalidInRangeJewelIndexX( $target ) ){
		return true;
	}else{
		return false;
	}
	return false;
}
private function isEqualJewelIndexX( $target:Jewel ):Boolean{
	return getJewelIndexX( getSelectedJewels()[0] ) === getJewelIndexX( $target );
}
private function isInvalidInRangeJewelIndexY( $target:Jewel ):Boolean{
	return ( getJewelIndexY( getSelectedJewels()[0] ) + 1 === getJewelIndexY( $target ) || getJewelIndexY( getSelectedJewels()[0] ) - 1 === getJewelIndexY( $target ) );
}
private function isEqualJewelIndexY( $target:Jewel ):Boolean{
	return getJewelIndexY( getSelectedJewels()[0] ) === getJewelIndexY( $target );
}
private function isInvalidInRangeJewelIndexX( $target:Jewel ):Boolean{
	return ( getJewelIndexX( getSelectedJewels()[0] ) + 1 === getJewelIndexX( $target ) || getJewelIndexX( getSelectedJewels()[0] ) - 1 === getJewelIndexX( $target ) );
}
private function getJewelIndexX( $target:Jewel ):int{
	return getJewelIndexInMap( $target )[0];
}
private function getJewelIndexY( $target:Jewel ):int{
	return getJewelIndexInMap( $target )[1];
}
private function getJewelIndexInMap( $target:Jewel ):Array{
	var i:int, j:int, k:int, l:int, map:Array, result:Array;
	
	result = [];
	map = getMap();
	for( i = 0, j = map.length ; i < j ; ++i ){
		if( isFindingJewel( map[i], $target ) ){
			result[result.length] = i;
			result[result.length] = map[i].indexOf( $target );
			return result;
		};
	}
	
	result = [-1, -1];
	return result;
}
private function isFindingJewel( $map:Array, $target:Jewel ):Boolean{
	return $map.indexOf( $target ) > -1;
}
private function addJewelFromSelectedJewels( $target:Jewel ):void{
	_model.selectJewel( $target );
	_view.selectJewel( $target );
}
private function shiftSelectedJewels( $tweenAfterCallback:Function = null ):void{
	shiftJewelsIndex( getSelectedJewels()[0], getSelectedJewels()[1] );
	_view.shiftJewels( getSelectedJewels()[0], getSelectedJewels()[1], function():void{
		if( $tweenAfterCallback is Function ){
			$tweenAfterCallback();
		}
	} );
}
private function returnSelectedJewels():void{
	if( haveSelectedJewels() ){
		shiftSelectedJewels( removeAllFromSelectedJewels );
	}
}
private function shiftJewelsIndex( $jewel1:Jewel, $jewel2:Jewel ):void{
	var jewel1Index:Array, jewel2Index:Array;
	
	jewel1Index = getJewelIndexInMap( $jewel1 );
	jewel2Index = getJewelIndexInMap( $jewel2 );
	setJewelToMap( $jewel1, jewel2Index[0], jewel2Index[1] );
	setJewelToMap( $jewel2, jewel1Index[0], jewel1Index[1] );
}
private function setJewelToMap( $target:Jewel, $indexX:int, $indexY:int ):void{
	getMap()[$indexX][$indexY] = $target;
}
private function removeAllFromSelectedJewels():void{
	var selected:Array;
	
	if( haveSelectedJewels() ){
		selected = getSelectedJewels();
		removeJewelFromSelectedJewels( selected[0] );
		removeJewelFromSelectedJewels( selected[0] );
	}
}
private function haveSelectedJewels():Boolean{
	return getSelectedJewels().length === 2;
}
private function getSelectedJewels():Array{
	return _model.getSelectedJewels()
}